# -*- coding: utf-8 -*-
# @Time    : 2019/4/26 9:07
# @Author  : shaoeric
# @Email   : shaoeric@foxmail.com

# -*- coding: utf-8 -*-
import numpy as np
from python_speech_features import logfbank, delta
import librosa


class Processsor:

    def __init__(self, file, alpha, beta, slice=False):
        super(Processsor, self).__init__()
        self.file = file
        self.slice = slice
        self.alpha = alpha
        self.beta = beta

    def get_fbank_feature(self, wavsignal, fs):
        """
        输入为wav文件数学表示和采样频率，输出为语音的FBANK特征+一阶差分+二阶差分
        :param wavsignal:
        :param fs:
        :return:
        """
        feat_fbank = logfbank(wavsignal, fs, nfilt=40, nfft=2048, winstep=0.025, winlen=0.05)
        feat_fbank_d = delta(feat_fbank, 2)
        feat_fbank_dd = delta(feat_fbank_d, 2)
        wav_feature = np.column_stack((feat_fbank, feat_fbank_d, feat_fbank_dd))
        return wav_feature

    def pre_process(self, y):
        """
        略微加强低频信号，并且使零频区域变为低频，不改变高频
        :param y: 音频信号
        :param alpha: 阈值比率，相对于极差的百分比
        :param beta: 预处理的力度
        :return: 处理后的信号
        """
        S = np.max(y) - np.min(y)
        thred = self.alpha * S
        for i in range(y.shape[0] - 1):
            if np.abs(y[i + 1] - y[i]) < thred:
                if y[i + 1] > y[i]:
                    y[i + 1] = (1 - self.beta) * y[i + 1]
                    y[i] = (1 + self.beta) * y[i]
                else:
                    y[i + 1] = (1 + self.beta) * y[i + 1]
                    y[i] = (1 - self.beta) * y[i]
                i += 1  # 跳过被修改过的位置
        return y

    def run(self):
        """
        :param filename: 选择的要进行风格分类的音乐文件
        :param slice: 是否进行3s的切片处理
        :return:
        """

        if not self.slice:
            y, sr = librosa.load(self.file)
            y = y[: 660000]

            mfcc = np.expand_dims(librosa.feature.mfcc(y=self.pre_process(y), n_mfcc=40).T, axis=0)
            f = np.expand_dims(self.get_fbank_feature(y, sr), axis=0)
            f = f + np.abs(f.min())
            return mfcc, f

        else:
            MFCC, logFBank = [], []
            for i in range(0, 27, 3):
                y, sr = librosa.load(self.file, offset=i, duration=3)
                mfcc = librosa.feature.mfcc(y=self.pre_process(y), n_mfcc=40)
                MFCC.append(mfcc.T)
                f = self.get_fbank_feature(y, sr)
                logFBank.append(f + np.abs(f.min()))
            return np.array(MFCC), np.array(logFBank)




